package com.minio.miniospringboot.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.minio.miniospringboot.common.Res;
import com.minio.miniospringboot.entity.UploadResult;
import com.minio.miniospringboot.service.MinioService;
import io.minio.*;
import io.minio.messages.Item;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.net.URLEncoder;
import java.text.DecimalFormat;
import java.util.*;

/**
 * @ClassName: MinioController
 * @auther: <Bang>
 * @Date: 2023/03/17 14:56
 * @Version: 1.0
 * @Modified By:
 */
@RestController
@Slf4j
public class MinioController {


    @Autowired
    private MinioService minioService;

    @GetMapping("/list")
    @ApiOperation("列出文件")
    public List<Object> list() throws Exception {
        //获取bucket列表
        Iterable<Result<Item>> myObjects = minioService.listObjects();
        Iterator<Result<Item>> iterator = myObjects.iterator();
        List<Object> items = new ArrayList<>();
        while (iterator.hasNext()) {
            Item item = iterator.next().get();
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("fileName", item.objectName());
            jsonObject.put("fileSize", formatFileSize(item.size()));
            jsonObject.put("isDir", item.isDir());
            items.add(jsonObject);
        }
        return items;
    }

    @PostMapping("/upload")
    @ApiOperation("上传文件")
    public Res upload(@RequestParam(name = "file", required = false)
                      MultipartFile multipartFile, @RequestParam(value = "rename", defaultValue = "true", required = false) boolean rename) throws Exception {
        if (multipartFile == null) {
            return Res.error("上传文件不能为空");
        }

        UploadResult upload = minioService.upload(multipartFile, rename);
        return Res.ok("上传成功", upload);
    }


    @GetMapping("/download/{fileName}")
    @ApiOperation("下载文件")
    public void download(HttpServletResponse response, @PathVariable("fileName")
    String fileName) {
        InputStream in = null;
        try {
            // 获取对象信息
            StatObjectResponse stat = minioService.statObject(fileName);
            response.setContentType(stat.contentType());
            response.setHeader("Content-Disposition", "attachment;filename=" +
                    URLEncoder.encode(fileName, "UTF-8"));
            in = minioService.getFile(fileName);
            IOUtils.copy(in, response.getOutputStream());
        } catch (Exception e) {
            log.error(e.getMessage());
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    log.error(e.getMessage());
                }
            }
        }
    }

    @DeleteMapping("/delete/{fileName}")
    @ApiOperation("删除文件")
    public Res delete(@PathVariable("fileName") String fileName) {
        try {
            minioService.delete(fileName);
        } catch (Exception e) {
            log.error(e.getMessage());
            return Res.error("删除失败");
        }
        return Res.ok("删除成功", null);
    }

    @PostMapping("/copy")
    @ApiOperation("复制文件")
    public Res copy(@RequestParam("source") String source, @RequestParam("target") String target) {
        try {
            ObjectWriteResponse copy = minioService.copy(source, target);
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("bucket",copy.bucket());
            jsonObject.put("filename",copy.object());
            return Res.ok("复制成功", jsonObject);
        } catch (Exception e) {
            log.error(e.getMessage());
            return Res.error("复制失败");
        }
    }


    @GetMapping("/getFileUrl/{filename}")
    @ApiOperation("获取文件地址")
    public Res getFileUrl(@PathVariable("filename") String filename) {
        try {
            String fileUrl = minioService.getFileUrl(filename);
            return Res.ok("获取文件地址成功", fileUrl);
        } catch (Exception e) {
            log.error(e.getMessage());
            return Res.error("获取文件地址失败");
        }
    }

    @PostMapping("setBucketPolicy/{bucketName}")
    @ApiOperation("设置bucket访问策略")
    public Res setBucketPolicy(@RequestBody BucketPolicyParam param) {
        try {
            minioService.setBucketPolicy(param.getBucket(), param.getConfig());
            return Res.ok("设置成功", null);
        } catch (Exception e) {
            log.error(e.getMessage());
            return Res.error("设置失败");
        }
    }

    @Data
    public static class BucketPolicyParam implements Serializable {

        @ApiModelProperty("策略")
        private String config;

        @ApiModelProperty("桶名称")
        private String bucket;

    }


    private static String formatFileSize(long fileS) {
        DecimalFormat df = new DecimalFormat("#.00");
        String fileSizeString = "";
        String wrongSize = "0B";
        if (fileS == 0) {
            return wrongSize;
        }
        if (fileS < 1024) {
            fileSizeString = df.format((double) fileS) + " B";
        } else if (fileS < 1048576) {
            fileSizeString = df.format((double) fileS / 1024) + " KB";
        } else if (fileS < 1073741824) {
            fileSizeString = df.format((double) fileS / 1048576) + " MB";
        } else {
            fileSizeString = df.format((double) fileS / 1073741824) + " GB";
        }
        return fileSizeString;
    }
}
